package com.lambo.maven.core.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author lambo
 */
public class HelpUtil {
    private static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    private static String DEFAULT_CHARSET_UTF8 = "UTF-8";
    private static String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    private static Logger logger = LoggerFactory.getLogger(HelpUtil.class);

    /**
     * MD5数字签名
     *
     * @param data 数据.
     * @return md5值 .
     */
    public static String md5Digest(byte[] data) {
        if (null == data) {
            return null;
        }
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("MD5");
            md.update(data);
            return bytesToHex(md.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * sha1自满.
     *
     * @param data 原生数据.
     * @return sha1签名.
     */
    public static String sha1Digest(byte[] data) {
        try {
            MessageDigest messagedigest = MessageDigest.getInstance("SHA1");
            return bytesToHex(messagedigest.digest(data));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA1 not exists", e);
        }
    }

    /**
     * 方法一：
     * byte[] to hex string
     *
     * @param bytes 数据流.
     * @return 16进制数据.
     */
    private static String bytesToHex(byte[] bytes) {
        // 一个byte为8位，可用两个十六进制位标识
        char[] buf = new char[bytes.length * 2];
        int a;
        int index = 0;
        // 使用除与取余进行转换
        for (byte b : bytes) {
            if (b < 0) {
                a = 256 + b;
            } else {
                a = b;
            }
            buf[index++] = HEX_CHAR[a / 16];
            buf[index++] = HEX_CHAR[a % 16];
        }
        return new String(buf);
    }


    /**
     * 签名文件. 支持循环目录签名.
     *
     * @param file 一般是文件或目录.
     */
    public static void signFile(File file) {
        if (null == file || !file.exists()) {
            return;
        }
        if (file.isFile()) {
            String name = file.getName().toLowerCase();
            if (!name.endsWith(".xml") && !name.endsWith(".jar") && !name.endsWith(".pom")) {
                return;
            }
            try {
                File sha1 = new File(file.getAbsolutePath() + ".sha1");
                File md5 = new File(file.getAbsolutePath() + ".md5");
                if (sha1.exists() && md5.exists()) {
                    return;
                }
                byte[] bytes = IoUtil.readToByteBuffer(file);
                if (!sha1.exists()) {
                    logger.info("create sha1, file = {}", sha1.getAbsolutePath());
                    IoUtil.writeFile(sha1.getAbsolutePath(), HelpUtil.sha1Digest(bytes).getBytes());
                }
                if (!md5.exists()) {
                    logger.info("create md5, file = {}", md5.getAbsolutePath());
                    IoUtil.writeFile(md5.getAbsolutePath(), HelpUtil.md5Digest(bytes).getBytes());
                }
            } catch (IOException e) {
                logger.error("signFile failed, file = {}", file.getAbsolutePath(), e);
            }
            return;
        }
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (null != files && files.length > 0) {
                for (File sub : files) {
                    signFile(sub);
                }
            }
        }
    }

    /**
     * 格式化输出日期.
     *
     * @param date 时间.
     * @return yyyy-MM-dd HH:mm:ss 格式.
     */
    public static String formatDateTime(Date date) {
        return new SimpleDateFormat(DATE_TIME_FORMAT).format(date);
    }

    /**
     * 文件名编码..
     *
     * @param fileName 文件名.
     * @return href.
     */
    public static String encodePath2Href(String fileName) {
        try {
            return URLEncoder.encode(fileName, DEFAULT_CHARSET_UTF8).
                    replace("+", "%20").
                    replace("%2F", "/");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("encodePath2Href:" + e.getLocalizedMessage(), e);
        }
    }
}
